package com.qiongqi.datadir.controller;

import com.qiongqi.datadir.common.AjaxResult;
import com.qiongqi.datadir.common.BaseController;
import com.qiongqi.datadir.common.page.TableDataInfo;
import com.qiongqi.datadir.config.DataDirConfig;
import com.qiongqi.datadir.domain.BucketQuota;
import com.qiongqi.datadir.helper.VaultHelper;
import com.qiongqi.datadir.service.IBucketQuotaService;
import com.qiongqi.datadir.service.IMinioService;
import com.qiongqi.datadir.service.IResourceService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.IterableUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import paillierp.key.PaillierPrivateThresholdKey;

import java.math.BigInteger;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.qiongqi.datadir.utils.security.HEUtils.paillierDecrypt;
import static org.apache.commons.collections4.CollectionUtils.isNotEmpty;
import static org.apache.commons.collections4.IterableUtils.size;
import static org.apache.commons.collections4.MapUtils.getString;
import static org.apache.commons.collections4.MapUtils.isEmpty;
import static org.apache.commons.lang3.StringUtils.isBlank;

@Slf4j
@Controller
@RequestMapping("/calc")
public class CalcController extends BaseController {

    @Autowired
    private DataDirConfig dataDirConfig;

    @Autowired
    private IMinioService minioService;

    @Autowired
    private IResourceService resourceService;

    @Autowired
    private IBucketQuotaService bucketQuotaService;

    @Autowired
    private VaultHelper vaultHelper;

    /**
     * 查询资源记录列表
     */
    @GetMapping
    public String index(Model model) {
        model.addAttribute("acconName", dataDirConfig.getName());
        return "calc.html";
    }

    /**
     * 查询资源记录列表
     */
    @GetMapping("/list")
    @ResponseBody
    public TableDataInfo list(BucketQuota bucketQuota) {
        startPage();
        List<BucketQuota> list = bucketQuotaService.selectBucketQuotaList(bucketQuota);
        return getDataTable(list);
    }


    /**
     * 添加数据资源
     * 调用示例: POST /addRes?bucketQuotaId=quota-123
     * Content-Type: application/json
     */
    @PostMapping("/process")
    @ResponseBody
    public AjaxResult process(
            @RequestBody Map<String, String> reqBody) throws Exception {
        // 验证输入数据
        if (isEmpty(reqBody)) {
            return AjaxResult.error("输入数据不能为空");
        }
        String inputData = getString(reqBody, "inputData");
        // 初始化累加结果为零
        BigInteger sum = BigInteger.ZERO;

        String[] lines = inputData.split("\\r?\\n");
        // 遍历每一行
        for (String line : lines) {
            // 跳过空行或空白行
            if (isBlank(line)) {
                continue;
            }
            try {
                // 将当前行字符串转换为 BigInteger
                BigInteger num = new BigInteger(line.trim());
                // 累加到总和中
                sum = sum.add(num);
            } catch (NumberFormatException e) {
                // 处理转换异常（例如包含非数字字符）
                log.error("无法将字符串转换为 BigInteger: {}", line);
                // 根据需求决定：跳过、终止或采取其他措施
                // 这里示例为跳过无法转换的行
            }
        }

        String decrypt = null;
        String bucketName = getString(reqBody, "bucketName");
        BucketQuota bq = bucketQuotaService.selectBucketQuotaByName(bucketName);
        List<String> parts = bq.getParticipants();
        if(isNotEmpty(parts)){
            int privKeyLen = size(parts);
            PaillierPrivateThresholdKey[] keys = new PaillierPrivateThresholdKey[privKeyLen];
            for(int idx = 0 ; idx < privKeyLen; idx ++){
                keys[idx] = vaultHelper.getPrivateKeyShare(bucketName, IterableUtils.get(parts, idx));
            }
            log.info("sum:{}", sum);
            decrypt = paillierDecrypt(keys, sum.toString());
        }
        Map<String, Object> ret = new HashMap<>();
        ret.put("inputLineCount", lines.length);
        ret.put("result", decrypt);
        log.info("lines:{}", ArrayUtils.toString(lines));
        return MapUtils.isNotEmpty(ret) ? success(ret) : error();
    }
}
